本页目录

内联汇编

asm! 宏让 Rust 直接嵌入目标机器的汇编指令——constraints 描述寄存器的输入/输出关系,clobbers 声明哪些寄存器被破坏。每条汇编模板都是 per-arch 的(x86_64 和 ARM64 写法完全不同),本质上是对编译器优化的一堵"请不要跨过这行做优化"的墙。

asm! 基础

use std::arch::asm;
let x: u64;
unsafe { asm!("rdtsc", out("rax") _, out("rdx") _, lateout("rax") x); }
// TSC (Time Stamp Counter) = EDX:EAX
// out("rax") _  — upper 32 bits, value discarded (_)
// out("rdx") _  — lower 32 bits in rdx, discarded
// lateout("rax") x — value combined in x

asm! 是 Rust 1.59+ 的新宏(取代旧的 llvm_asm!)。编译时检查约束的正确性——寄存器冲突、invalid operand、type mismatch 都会在编译期报告。

Constraints: 输入输出规范

let mut a: u64 = 4;
let b: u64 = 4;
unsafe {
    asm!(
        "add {0}, {1}",              // {0} = a, {1} = b
        inlateout(reg) a,            // a: 输入+输出, 不与输入共享寄存器
        in(reg) b,                   // b: 纯输入
    );
}
  • in(reg): 输入,编译器分配寄存器,加载值
  • out(reg): 输出,读取最终值
  • inout(reg): 输入+输出
  • lateout(reg): 输出,不与输入共享寄存器(用于输入寄存器被 clobber 的场景)
  • inlateout(reg): 输入+输出,不与输入共享寄存器

Clobbers: 哪些寄存器被修改

outlateout 自动标记对应寄存器为 clobbered。但如果调用了其他函数,需要标记整个 ABI 的 clobber 集合:

unsafe {
    asm!(
        "call my_function",
        clobber_abi("C"),            // 所有 C calling convention 的 caller-saved 寄存器被标记 clobbered
    );
}

per-arch 条件编译

#[cfg(target_arch = "x86_64")]
unsafe { asm!("rdtsc", ...); }

#[cfg(target_arch = "aarch64")]
unsafe { asm!("mrs {}, cntvct_el0", out(reg) x); }  // ARM64 的 cycle counter

Options

asm!("nop", options(nomem, nostack, preserves_flags));
// nomem:    不读写内存 (编译器可以不刷新缓存)
// nostack:  不 push/pop 栈
// preserves_flags: 不修改 EFLAGS/RFLAGS
// pure:     无副作用 (可被优化消除)
// readonly: 只读内存

参考

  • Rust Reference: inline assembly
  • Rust By Example: asm

Keywords: asm!, inline assembly, constraints, clobbers, lateout, clobber_abi, per-arch asm